/*
 * Copyright 2009 BioTeam Inc
 * 
 * Licensed under License GNU LESSER GENERAL PUBLIC LICENSE version 3.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.gnu.org/copyleft/lesser.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package net.bioteam.appweb.gwt.apps.server.program;

import java.beans.XMLDecoder;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;

import net.bioteam.appweb.Config;
import net.bioteam.appweb.gwt.apps.clientandserver.Constant;
import net.bioteam.appweb.gwt.apps.clientandserver.ServerException;
import net.bioteam.appweb.gwt.apps.clientandserver.program.GetProgramSpec;
import net.bioteam.appweb.gwt.apps.server.MyRemoteServiceServlet;
import net.bioteam.appweb.gwt.apps.server.UnsupportedUserFileTypeException;
import net.bioteam.appweb.model.Program;
import net.bioteam.appweb.model.ProgramBuilder;
import net.bioteam.appweb.model.ProgramTemplate;
import net.bioteam.appweb.model.ProgramTemplateUtil;
import net.bioteam.appweb.submit.ProgramValueBean;
import net.bioteam.common.user.User;
import net.bioteam.common.utils.MyEntityManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Work together with TreeDataServlet
 * 
 *TODO check template file existence
 * @author jason
 * 
 */
public class GetProgramSpecImpl extends MyRemoteServiceServlet implements GetProgramSpec
{
	private static final long serialVersionUID = 1L;
	public final static Log logger=LogFactory.getLog(GetProgramSpecImpl.class);

	public ProgramValueBean getProgram(String ptype, String pvalue) throws ServerException
	{

		User user=(User)getThreadLocalRequest().getSession().getAttribute("user");
		try
		{
			if (ptype.equals(Constant.global_template_ptype))
			{
				String filename = pvalue;
				int index = filename.indexOf('_');
				String programName = filename.substring(0, index);
				Program p = ProgramBuilder.getProgram(programName);
				if (p == null)
				{
					throw new ServerException(programName + " is already removed from system");
				}

				File savedDir = new File(Config.topdir + File.separator + Config.TEMPLATE_DIR + File.separator + Config.PUBLIC_TEMPLATE_DIR);
				ProgramValueBean bean = new ProgramValueBean(p);
				// global template
				File templateFile = new File(savedDir.getAbsolutePath() + File.separator + filename);
				getBean(templateFile, bean, user);
				if (p.getMetaData().containsKey(Constant.email_key))
				{
					bean.setValue(Constant.email_key, user.getEmail());
				}
				return bean;

			} else if (ptype.equals(Constant.user_template_ptype))
			{
				// user template
				EntityManager em = MyEntityManager.getEntityManager();
				ProgramTemplate run = em.find(ProgramTemplate.class, Long.parseLong(pvalue));
				String username =user.getName();
				Program p = ProgramBuilder.getProgram(run.getProgramName());
				if (p == null)
				{
					throw new ServerException(run.getProgramName() + " is already removed from system");
				}

				ProgramValueBean bean = new ProgramValueBean(p);
				File templateFile = new File(Config.topdir + File.separator + Config.TEMPLATE_DIR + File.separator + username + File.separator + 
						ProgramTemplateUtil.getFilename(run));

				getBean(templateFile, bean, user);
				if (p.getMetaData().containsKey(Constant.email_key))
				{
					bean.setValue(Constant.email_key, user.getEmail());
				}
				return bean;
			} else
			{
				Program p;
				p = ProgramBuilder.getProgram(pvalue);
				ProgramValueBean bean=new ProgramValueBean(p);
				if (p.getMetaData().containsKey(Constant.email_key))
				{
					bean.setValue(Constant.email_key, user.getEmail());
				}
				return bean;
			}
		} catch (Exception e)
		{
			throw new ServerException(e.getMessage());
		}

	}

	private ProgramValueBean getBean(File templateFile, ProgramValueBean bean, User user) throws ServerException
	{
		Program p = bean.getProgram();
		XMLDecoder d = null;
		try
		{
			d = new XMLDecoder(new BufferedInputStream(new FileInputStream(templateFile)));
		} catch (FileNotFoundException e)
		{
			throw new ServerException(e.getMessage());
		}

		Object result = d.readObject();
		d.close();
		Map<String, Object> mapResult = (Map<String, Object>) result;
		Map<String, String> maps = new HashMap<String, String>();
		for (Map.Entry<String, Object> entry : mapResult.entrySet())
		{
			maps.put(entry.getKey(), entry.getValue().toString());
		}
		for (String key: maps.keySet())
		{
			if (key.endsWith(Constant.file_server_suffix))
			{
				if (!isServerFilevalid(maps.get(key), user.getName()))
				{
					maps.remove(key);
				}
			}
		}
		bean.setValueMap(maps);
		return bean;
	}
	
	
	public static boolean isServerFilevalid(String webString, String username) 
	{
		String fileName;
		try
		{
			fileName = ProgramHandler.webStringToRealFile(webString, username);
		} catch (UnsupportedUserFileTypeException e)
		{
			return false;
		}
		return new File(fileName).exists();
	}

//	public ParameterMap loadParameterMap(String programName) throws ServerException
//	{
//		ParameterMap maps=ParameterMapBuilder.dataMaps.get(programName);
//		if (maps==null)
//		{
//			return new ParameterMap();
//		} else
//		{
//			return maps;
//		}
//	}
//
//	public String saveParameterMap(String programName, ParameterMap map) throws ServerException
//	{
//		File file=new File(Config.PARAMETER_MAP_DIR+File.separator+programName+".xml");
//		
//		try
//		{
//			Program p=ProgramBuilder.getProgram(programName);
//			OutputStream out=new FileOutputStream(file);
//			for (TypeMap type:map.getTypeMaps())
//			{
//				if (type.isInput()==null)
//				{
//					Parameter param=p.getParameter(programName);
//					type.setInput(param.getType()==ParameterType.OutputFileType?false:true);
//				}
//			}
//			ParameterMapBuilder.outputMap(map, out);
//			out.close();
//			ParameterMapBuilder.dataMaps.put(programName, map);
//		} catch (Exception e)
//		{
//			logger.warn("error when save parameterMap", e);
//			throw new ServerException(e.getMessage());
//		}
//		return "saved successfully";
//	}
}
